<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace xsl\services;

use App\Exception\AppException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use UnexpectedValueException;
use xsl\enums\Code;

class JwtTokenService
{

    const SECRET = 'VliwSuvne';//密钥

    /**
     * @return array
     */
    public function createToken(int $id, string $type, $exp, array $params, $domain)
    {
        $time = time();
        $host = $domain;
        $params += [
            'iss' => $host, // 签发者
            'aud' => $host,
            'iat' => $time, // 签发时间
            'nbf' => $time,
            'exp' => $exp, // 过期时间
        ];
        $params['jti'] = [$id, $type];
        $token = JWT::encode($params, self::SECRET,'HS256');
        $params['token'] = $token;
        $params['out'] = $exp - time();
        return $params;
    }

    /**
     * @return object
     * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
     * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
     * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
     * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
     * @throws UnexpectedValueException Provided JWT was invalid
     */
    public function parseToken(string $token)
    {
        return JWT::decode($token, new Key(self::SECRET, 'HS256'));
    }

    /**
     * @return object
     */
    public function decode(string $token)
    {
        $tks = explode('.', $token);
        if (count($tks) != 3) {
            throw new AppException('Invalid token', Code::FAILED);
        }

        if (null === $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($tks[1]))) {
            throw new AppException('Invalid token', Code::FAILED);
        }

        return $payload;
    }
}
